/*global pi, window, document, location */
// 界面管理器模块，所有的界面都是由forelet构成。
// 模块加载前，将会动态寻找如果根节点，首先检查pi.config.root上设置的节点或节点名，其次寻找id为被设置的节点名或foreletRoot的节点，如果找不到节点，则创建节点，并且将节点设为网页可见区域宽高。
// forelet实际是在root节点上的一个iframe，创建forelet就是创建iframe，并设置对应页面的内容，包括css, js。
// 后期优化界面打开速度，可以预创建及缓存一些iframe。

pi.mod.define('pi.forelet', function(pi) {
	"use strict";
	// 定义模块
	var module = {},
	table = {},
	wait = {},
	iframe = [],
	iframeWait = [],
	linkTable = {},
	topIndex = 1,
	doc = document,
	//根结点
	root = (function(r) {
		var node = r;
		if (pi.lang.isString(r)) {
			node = doc.getElementById(r);
			if (!node) {
				node = doc.createElement("div");
				node.setAttribute("id", r);
				node.scrolling = "no";
				node.style.border = "0px";
				node.style.position = "absolute";
				node.style.width = doc.body.clientWidth;
				node.style.height = doc.body.clientHeight;
				doc.body.appendChild(node);
			}
		}
		return node;
	} (pi.config.root || "foreletRoot")),

	//创建iframe结点
	createIframe = function() {
		var node = pi.html.createIframeNode(doc);
		node.onload = function() {
			node.onload = undefined;
			if (iframeWait.length > 0) {
				iframeWait.shift()(node);
			} else {
				iframe.push(node);
			}
			node = undefined;
		};
		root.appendChild(node);
	},
	// 添加键类型对应的link
	addLink = function(key, type, link) {
		var arr, node = linkTable[key];
		if (!node) {
			node = {};
			linkTable[key] = node;
		}
		arr = node[type];
		if (arr) {
			arr.push(link);
		}else{
			node[type] = [link];
		}
	},
	// 获得键类型对应的link
	getLink = function(key, type) {
		var i, arr, node = linkTable[key];
		if(!node){
			return [];
		}
		if(type){
			arr = node[type];
			return arr ? arr : [];
		}else{
			arr = [];
			for(i in node){
				if (node.hasOwnProperty(i)) {
					arr.concat(node[i]);
				}
			}
			return arr;
		}
	},
	// 引发类型对应的link
	fireLink = function(key, type, callback) {
		var i, arr = getLink(key, type);
		for(i = arr.length - 1; i >= 0; i--){
			callback(arr[i].link);
		}
	},
	// 删除键类型对应的link
	removeLink = function(key, forelet, type) {
		var i, n, arr, node = linkTable[key];
		if(!node){
			return;
		}
		arr = node[type];
		if(!arr){
			return;
		}
		for(i = n = arr.length - 1; i >= 0; i--){
			if(arr[i].link === forelet){
				arr[i] = arr[n];
				arr.length = n--;
				break;
			}
		}
		if(n > 0){
			return;
		}
		delete node[type];
		for(i in node){
			if (node.hasOwnProperty(i)) {
				return;
			}
		}
		delete linkTable[key];
	},
	// 删除键类型对应的link
	delLink = function(forelet1, forelet2, type) {
		var i, arr, link, key = forelet1.getKey(), node = linkTable[key];
		if(!node){
			return;
		}
		arr = getLink(key, type);
		if(forelet2){
			for(i = arr.length - 1; i >= 0; i--){
				link = arr[i];
				if(link === forelet2){
					removeLink(forelet2.getKey(), forelet1, link.type);
				}
			}
		}else{
			for(i = arr.length - 1; i >= 0; i--){
				link = arr[i];
				removeLink(forelet2.getKey(), link.link, link.type);
			}
		}
		if(type){
			delete node[type];
			for(i in node){
				if (node.hasOwnProperty(i)) {
					return;
				}
			}
		}
		delete linkTable[key];
	},
	// 获得左边或上边的坐标
	getLeft = function(array, width) {
		var i, n, e, left = 0;
		for (i = 0, n = array.length; i < n; i++) {
			e = array[i];
			if (pi.lang.isNumber(e)) {
				// 处理数字
				left += e;
			} else {
				// 处理百分比
				e = Math.round(pi.lang.parseIntUnsafe(e) * (width - left) / 100);
				left += e;
			}
		}
		return left;
	},
	// 获得右边或下边的坐标
	getRight = function(array, width) {
		var i, n, e, left = width;
		for (i = 0, n = array.length; i < n; i++) {
			e = array[i];
			if (pi.lang.isNumber(e)) {
				// 处理数字
				left -= e;
			} else {
				// 处理百分比
				e = Math.round(pi.lang.parseIntUnsafe(e) * left / 100);
				left -= e;
			}
		}
		return left;
	},

	// 调用等待的回调
	callWait = function(wait, key, forelet) {
		var i, arr = wait[key];
		delete wait[key];
		for (i = arr.length - 1; i >= 0; i--) {
			arr[i](forelet);
		}
	},

	// 向指定的forelet发送消息
	sendMessage = function(forelet, msgMethod, msg) {
		var receive = forelet.msgReceive;
		if (receive) {
			if (msgMethod) {
				if (receive[msgMethod]) {
					return receive[msgMethod](msg);
				}
			} else {
				return receive(msg);
			}
		}
		return undefined;
	},

	// 关闭指定的forelet
	close = function(forelet) {
		var key, glass, i, arr;
		if (pi.lang.isString(forelet)) {
			key = forelet;
			forelet = table[key];
		} else {
			key = forelet.getKey();
		}
		delete table[key];
		glass = forelet.getGlass();
		if(glass){
			root.removeChild(glass);
		}
		root.removeChild(forelet.getNode());
		// 防止内存泄漏，将事件处理器移除
		pi.ui.event.unbind(forelet.getWin().document.body, forelet.getHandler());
		if (forelet === pi.ui.tooltip.getForelet()) {
			pi.ui.tooltip.set();
		}
		arr = getLink(key, "close");
		delLink(forelet);
		for(i = arr.length - 1; i >= 0; i--){
			module.remove(arr[i].link);
		}
		if (forelet.destroy) {
			forelet.destroy();
		}
	},
	// 创建Forelet
	createForelet = function(key, url, cfg, node) {
		var glass, forelet = {},
		win = pi.html.getIFrameWindow(node),
		handler = pi.ui.event.createHandlerTable(forelet);
		// 获得forelet的键
		forelet.getKey = function() {
			return key;
		};
		// 获得forelet的url
		forelet.getUrl = function() {
			return url;
		};
		// 获得forelet的配置
		forelet.getCfg = function() {
			return cfg;
		};
		// 获得forelet的节点
		forelet.getNode = function() {
			return node;
		};
		// 获得forelet对应的玻璃面板
		forelet.getGlass = function() {
			return glass;
		};
		// 获得forelet的窗口根对象
		forelet.getWindow = function() {
			return win;
		};
		// 获得forelet的事件处理表
		forelet.getHandler = function() {
			return handler;
		};
		// 设置forelet是否显示
		forelet.show = function(show) {
			node.style.display = (show ? "": "none");
		};
		// 判断forelet是否显示
		forelet.isShow = function() {
			return node.style.display === "none";
		};
		// 提升界面到顶部
		forelet.front = function() {
			node.style.zIndex = ++topIndex;
		};
		// 获得forelet的内容宽度
		forelet.contentWidth = function() {
			return pi.html.contentWidth(win.document);
		};
		// 获得forelet的内容高度
		forelet.contentHeight = function() {
			return pi.html.contentHeight(win.document);
		};
		// forelet自动调整大小以适应内容
		forelet.autoSize = function() {
			var doc = win.document;
			node.style.width = pi.html.contentHeight(doc) + "px";
			node.style.height = pi.html.contentWidth(doc) + "px";
		};
		// forelet关闭
		forelet.close = function() {
			close(forelet);
		};
		// 初始化开始，
		forelet.initStart = function(result) {
			if (result.error) {
				root.removeChild(node);
				return callWait(wait, key, result);
			}
			table[key] = forelet;
			callWait(wait, key, forelet);
			if (forelet.init) {
				forelet.init(cfg.init);
			} else {
				forelet.initHandler();
				forelet.initShow();
			}
		};
		// 根据配置初始化事件处理器
		forelet.initHandler = function() {
			//设置鼠标事件可以穿透界面，必须第一个添加
			if (cfg.pointPenetrate) {
				handler.add(function(e) {
					switch (e.type) {
					case "mousedown":
					case "mouseup":
					case "mouseover":
					case "mouseout":
					case "mousemove":
					case "click":
					case "dblclick":
						break;
					default:
						return;
					}
					// TODO，派发事件到其他forelet中，要提前修正位置和e.target
				});
			}
			//设置是否处理界面上的按钮
			if (cfg.handleButton === undefined || cfg.handleButton) {
				pi.ui.button.bind(handler);
			}
			//设置界面上的提示处理器
			pi.ui.tooltip.bind(handler);
			//设置是否拖放选择内容
			//设置是否右键关闭界面
			// 设置是否鼠标按下时提升界面到顶部
			if (cfg.pressFront) {
				handler.addPre(function() {
					if (node.style.zIndex !== topIndex) {
						node.style.zIndex = ++topIndex;
					}
				});
			}
			// 设置是否界面可拖动，定义了拖动区域的属性对象可以引发界面拖动
			if (cfg.dragArea) {
				// TODO
			}
			pi.ui.event.bind(win.document.body, handler);
		};
		// 根据配置初始化显示
		forelet.initShow = function() {
			var rootWidth = pi.html.getWidth(root),
			rootHeight = pi.html.getHeight(root),
			style = node.style,
			width = 0,
			height = 0,
			left,
			right;
			// 设置宽高
			if (cfg.sizeWidth) {
				if (pi.lang.isNumber(cfg.sizeWidth)) {
					width = cfg.sizeWidth;
				} else {
					width = Math.round(pi.lang.parseIntUnsafe(cfg.sizeWidth) * rootWidth / 100);
				}
			} else {
				width = forelet.contentWidth();
			}
			if (width) {
				style.width = width + "px";
			}
			if (cfg.sizeHeight) {
				if (pi.lang.isNumber(cfg.sizeHeight)) {
					height = cfg.sizeHeight;
				} else {
					height = Math.round(pi.lang.parseIntUnsafe(cfg.sizeHeight) * rootHeight / 100);
				}
			} else {
				height = forelet.contentHeight();
			}
			if (height) {
				style.height = height + "px";
			}
			// 设置位置
			// 计算左边位置
			if (cfg.offsetLeft !== undefined) {
				left = pi.lang.isArray(cfg.offsetLeft) ? getLeft(cfg.offsetLeft, rootWidth) : cfg.offsetLeft;
			}
			// 计算右边位置
			if (cfg.offsetRight !== undefined) {
				right = pi.lang.isArray(cfg.offsetRight) ? getRight(cfg.offsetRight, rootWidth) : rootWidth - cfg.offsetRight;
			}
			// 如果左右都有则居中
			if (left !== undefined && right !== undefined) {
				style.left = (Math.round((right + left - width) / 2)) + "px";
			} else if (left) {
				style.left = (left) + "px";
			} else if (right) {
				style.left = (rootWidth - right - width) + "px";
			}
			left = right = undefined;
			// 计算上边位置
			if (cfg.offsetTop) {
				left = pi.lang.isArray(cfg.offsetTop) ? getLeft(cfg.offsetTop, rootHeight) : cfg.offsetTop;
			}
			// 计算下边位置
			if (cfg.offsetBottom) {
				right = pi.lang.isArray(cfg.offsetBottom) ? getRight(cfg.offsetBottom, rootHeight) : rootHeight - cfg.offsetBottom;
			}
			// 如果上下都有则居中
			if (left !== undefined && right !== undefined) {
				style.top = (Math.round((right + left - width) / 2)) + "px";
			} else if (left) {
				style.top = (left) + "px";
			} else if (right) {
				style.top = (rootHeight - right - width) + "px";
			}
			// 设置玻璃面板
			if (cfg.glass) {
				glass = doc.createElement('div');
				glass.setAttribute("glass", key);
				glass.style.position = "absolute";
				glass.style.width = "100%";
				glass.style.height = "100%";
				glass.style.zIndex = ++topIndex;
				if(cfg.glass.pressClose){
					pi.html.bind(glass, "mousedown", forelet.close);
				}
				if(cfg.glass.bgcolor){
					glass.style.background = cfg.glass.bgcolor;
				}
				if(cfg.glass.alpha){
					glass.style.opacity = cfg.glass.alpha;
					glass.style.filter = "alpha(opacity:" + cfg.glass.alpha + ")";
				}
				root.appendChild(glass);
				style.zIndex = ++topIndex;
				style.display = "";
			}else{
				// 设置是否自动提升界面到顶部
				if (cfg.front) {
					style.zIndex = ++topIndex;
				}
				if (cfg.show === undefined || cfg.show) {
					style.display = "";
				}
			}
		};
		// forelet上指定元素的左偏移的坐标
		forelet.offsetLeft = function(el) {
			return pi.html.offsetLeft(el) + node.offsetLeft;
		};
		// forelet上指定元素的上偏移的坐标
		forelet.offsetTop = function(el) {
			return pi.html.offsetTop(el) + node.offsetTop;
		};
		// forelet上指定元素的偏移的坐标
		forelet.offsetPos = function(el) {
			var pos = pi.html.offsetPos(el);
			pos[0] += node.offsetLeft;
			pos[1] += node.offsetTop;
			return pos;
		};
		// forelet广播消息或向其他forelet发送消息
		forelet.send = function(msgMethod, msg, targetForelet) {
			var i;
			if (targetForelet) {
				targetForelet = table[targetForelet];
				return targetForelet ? sendMessage(targetForelet, msgMethod, msg) : undefined;
			}
			for (i in table) {
				if (i !== key && table.hasOwnProperty(i)) {
					sendMessage(table[i], msgMethod, msg);
				}
			}
			return true;
		};
		// forelet上执行函数，如果函数没有注册在forelet上，则执行forelet所在window上的方法
		forelet.exec = function(func, args) {
			var name = forelet[func];
			func = (name) ? name: win[func];
			return (func) ? func.apply(undefined, args) : undefined;
		};
		return forelet;
	},

	// 初始化节点，先注入css，然后设置body，注入初始化js
	initForelet = function(forelet, mix, page, node) {
		var i, n, arr, win = forelet.getWindow(),
		doc = win.document,
		head = pi.html.getHead(doc);
		arr = page.css;
		for (i = 0, n = arr.length; i < n; i++) {
			node = pi.html.createCssNode(doc, arr[i]);
			head.appendChild(node);
		}
		doc.body.innerHTML = pi.ui.page.mixBody(page, mix);
		win.pi = pi;
		win.forelet = forelet;
		node = pi.html.createJsNode(doc, "pi.html.loadJS(document,['" + page.js.join("','") + "']," + "function(r){forelet.initStart(r);});");
		head.appendChild(node);
	},
	// 创建DOM节点的方法
	createNode = function(key, url, cfg, mix, page) {
		var node, len = iframe.length - 1;
		if (len >= 0) {
			node = iframe[len];
			iframe.length = len;
			node.id = key;
			initForelet(createForelet(key, url, cfg, node), mix, page, node);
		} else {
			iframeWait.push(function(node) {
				node.id = key;
				initForelet(createForelet(key, url, cfg, node), mix, page, node);
			});
		}
		createIframe();
	};

	// 缓存2个iframe
	createIframe();
	createIframe();
	//初始化全局tooltip
	pi.ui.tooltip.init(root);

	/**
	 * *添加一个窗口面板
	 * @param {string}
	 *		key 窗体的的key值
	 * @param {string}
	 *		url 窗体请求页面所在的地址
	 * @param {Object}
	 *		cfg 窗体配置参数json {
				sizeWidth:undefined | Number | "10%",
				sizeHeight:undefined | Number | "10%",
				offsetLeft:undefined | Number | ["10%", 20, ...],
				offsetRight:undefined | Number | ["10%", 20, ...],
				offsetTop:undefined | Number | ["10%", 20, ...],
				offsetBottom:undefined | Number | ["10%", 20, ...],
				front:undefined | true | false, // undefined等同于false
				show:undefined | true | false, // undefined等同于true
				rightClick:undefined | true | false, // undefined等同于false
				autoFront:undefined | true | false, // undefined等同于false
			}
	 * @param {Object}
	 *		mix 页面混合对象
	 * @param {Function}
	 *		callback 创建forelet成功后的回调
	 */
	module.create = function(key, url, cfg, mix, callback) {
		var forelet = table[key];
		// 当窗体面板存在页面内的时候，立即回调
		if (forelet) {
			callback(forelet);
			return;
		}
		// 如果窗体正在加载，则放入等待队列
		if (wait[key]) {
			wait[key].push(callback);
			return;
		}
		wait[key] = [callback];
		url = pi.mod.absUrl(url, location.href);
		// 加载指定的页面
		pi.ui.page.load(url, function(page) {
			if (page.error) {
				return callWait(wait, key, page);
			}
			createNode(key, url, cfg, mix, page);
		});
	};

	// 通过key获取forelet对象
	module.get = function(key) {
		return table[key];
	};
	// 通过指定的位置获得对应的forelet
	module.getByPos = function(x, y) {
		var i, f, n, pos, front, z = 0;
		for (i in table) {
			if (table.hasOwnProperty(i)) {
				f = table[i];
				n = f.getNode();
				pos = n.offsetLeft;
				if (x < pos || x > pos + n.offsetWidth) {
					continue;
				}
				pos = n.offsetTop;
				if (y < pos || y > pos + n.offsetHeight) {
					continue;
				}
				pos = n.style.zIndex;
				if (z > pos) {
					continue;
				}
				z = pos;
				front = f;
			}
		}
		return front;
	};
	// 关闭指定的forelet
	module.close = function(forelet) {
		close(forelet);
	};

	// forelet1链接forelet2，type为类型（close, pos）
	module.link = function(forelet1, forelet2, type) {
		addLink(forelet1.getKey(), type, {
			link: forelet2,
			type: type
		});
		addLink(forelet2.getKey(), type, {
			link: forelet1,
			type: type
		});
	};
	// 取消forelet1与forelet2的链接，如果没有forelet2则取消所有forelet1的链接，type为类型（close, pos）
	module.unlink = function(forelet1, forelet2, type) {
		delLink(forelet1.getKey(), forelet2 ? forelet2.getKey() : undefined, type);
	};
	return module;
});